﻿#include "ZdsjWindow.h"
// #include <iostream>

ZdsjWindow::ZdsjWindow(HWND parent, HINSTANCE hinstance)
{
    // 设置窗口大小
    RECT rect = {};
    GetWindowRect(parent, &rect);
    this->_rect = new RECT;
    this->_rect->left = rect.left + 150;
    this->_rect->top = 0;
    this->_rect->right = rect.left + 150 + 200;
    this->_rect->bottom = this->_rect->top + this->getHeight(&rect);
    
    // 1. 设置窗口类并注册
    if(!this->registerClass(hinstance))
    {
        exit(REGISTER_ERROR_EXIT);
    }
    
    // 2. 创建窗口
    if(!this->createWindow(hinstance))
    {
        exit(CREATEWINDOW_ERROR_EXIT);
    }
    // ShowWindow(this->_hwnd, 1);
    // 3. 设置系统托盘
    this->_menu = new Menu();
    this->_taskTray = new TaskTray(this->_hwnd, this->_menu->getMenu());
    // 4. 设置父窗口并显示
    SetParent(this->_hwnd, parent);
    SetWindowPos(this->_hwnd, HWND_TOP, this->_rect->left, this->_rect->top,
        this->getWidth(this->_rect), this->getHeight(this->_rect), SWP_DEFERERASE);
    SetLayeredWindowAttributes(this->_hwnd, NULL, 255, LWA_COLORKEY);
    
    ShowWindowAsync(this->_hwnd, 1);
    // BLENDFUNCTION stBlend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
    // UpdateLayeredWindow(this->_hwnd, NULL, NULL, NULL, NULL, NULL, RGB(255,255,255), &stBlend, ULW_ALPHA| ULW_COLORKEY);
}

ZdsjWindow::~ZdsjWindow()
{
    UnregisterClass(this->_className, NULL);
    delete this->_rect;
    if(this->_hwnd != NULL)
    {
        DestroyWindow(this->_hwnd);
    }
}

HWND ZdsjWindow::getHwnd()
{
    return this->_hwnd;
}

bool ZdsjWindow::registerClass(HINSTANCE hinstance)
{
    WNDCLASSEXW wndclass = {};
    wndclass.cbSize = sizeof(wndclass);
    wndclass.style = CS_HREDRAW | CS_VREDRAW ;
    wndclass.lpfnWndProc = HandelMsgSetUp;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hinstance;
    wndclass.hIcon = NULL;
    // MAKEINTRESOURCE()
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    // wndclass.hCursor = NULL;
    wndclass.hbrBackground = (HBRUSH)GetStockObject(COLOR_BTNSHADOW);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = this->_className;
    return RegisterClassExW(&wndclass);
}

bool ZdsjWindow::createWindow(HINSTANCE hinstance)
{
    this->_hwnd = CreateWindowExW(
        WS_EX_LAYERED,
        // WS_EX_NOREDIRECTIONBITMAP,
        this->_className,
        this->_windowName,
        WS_POPUP,
        this->_rect->left,
        this->_rect->top,
        this->getWidth(this->_rect),
        this->getHeight(this->_rect),
        NULL,
        NULL,
        hinstance,
        this
    );
    return this->_hwnd != NULL;
}

int ZdsjWindow::getWidth(const RECT* rect)
{
    return rect->right - rect->left;
}

int ZdsjWindow::getHeight(const RECT* rect)
{
    return rect->bottom - rect->top;
}

LRESULT ZdsjWindow::HandelMsgSetUp(HWND handle, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (msg == WM_NCCREATE) {
        // 创建窗口时触发
        // lParam 指向 CREATESTRUCT 结构的指针，其中包含有关正在创建的窗口的信息。
        // CREATESTRUCT.lpCreateParams 也就是CreateWindowExW的LPVOID指向的指针
        const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
        ZdsjWindow* const pwnd = static_cast<ZdsjWindow*>(pCreate->lpCreateParams);
        // 将执行CreateWindowExW的this指针存入窗口
        SetWindowLongPtrW(handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pwnd));
        // 不能通过WINAPI调用成员函数, 在将此函数设置为消息处理函数后，被当作WINAPI了
        // 将消息转发到静态方法
        // GWLP_WNDPROC设置窗口过程的新地址
        SetWindowLongPtrW(handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&ZdsjWindow::HandelMsgForward));
        return pwnd->HandelMsg(handle, msg, wParam, lParam);
    }
    return DefWindowProc(handle, msg, wParam, lParam);
}

LRESULT ZdsjWindow::HandelMsgForward(HWND handle, UINT msg, WPARAM wParam, LPARAM lParam)
{
    ZdsjWindow* const pwnd = reinterpret_cast<ZdsjWindow*>(GetWindowLongPtrW(handle, GWLP_USERDATA));
    return pwnd->HandelMsg(handle, msg, wParam, lParam);
}

LRESULT ZdsjWindow::HandelMsg(HWND handle, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    WORD event;
    switch (msg)
    {
    case WM_SETCURSOR:
        LOWORD(lParam);
        event = HIWORD(lParam);
        switch (event)
        {
        case WM_MOUSEMOVE:
            // 目前只能move触发
            break;
        case WM_MOUSEHOVER :
            // xPos = GET_X_LPARAM(lParam); 
            // yPos = GET_Y_LPARAM(lParam);
            // std::cout << "x: " << xPos << " y: " << yPos << std::endl;
            break;
        case WM_RBUTTONDBLCLK:
            // std::cout << "rclick" << std::endl;
            break;
        }
        break;
    case WM_SIZE:
        //
        // width = LOWORD(lParam);
        // height = HIWORD(lParam);
        // std::cout << "size" << " width: " << width << " height: " << height << std::endl;
        break;
    case WM_PAINT:
        break;
    case WM_NCPAINT:
        break;
    case WM_CREATE://窗口创建时候的消息.
        break;
    case WM_USER://连续使用该程序时候的消息.
        break;
    case WM_DESTROY://窗口销毁时候的消息.
        PostQuitMessage(0);
        break;
    default:
        break;
    }
    if (this->_menu != nullptr) {
        switch (msg)
        {
        case WM_COMMAND:
            this->_menu->dealMenuMessage(handle, msg, wParam, lParam);
            break;
        }
    }
    // 处理系统托盘消息
    if (this->_taskTray != nullptr) {
        this->_taskTray->dealTaskBarMessage(handle, msg, wParam, lParam);
    }
    return DefWindowProc(handle, msg, wParam, lParam);
}
